import 'package:dio/dio.dart';
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';
import 'package:my_app/base/foundation/flutter_extension.dart';
import 'package:my_app/base/widget/basic/base_lifecycle_page.dart';
import 'package:my_app/base/widget/basic/base_list_report.dart';
import 'package:my_app/base/widget/image/jd_asset_image.dart';
import 'package:my_app/modules/widgets/jd_button.dart';

import '../../foundation/jd_device.dart';
import '../../foundation/list_value_notifier.dart';
import '../../net/jd_request.dart';
import '../../utils/jd_log.dart';
import '../../utils/loading_util.dart';
import '../image/jd_network_image.dart';
import '../pages/empty_page.dart';
import '../refresh/jd_loading_footer.dart';
import '../refresh/jd_refresh_header.dart';

mixin BaseListWidgetMixin<Data, T extends StatefulWidget> on State<T> {
  final ListValueNotifier<Data> _listValueNotifier = ListValueNotifier();

  /// 请求服务器的 URL
  @required
  JDApiRequest get apiUrlRequest;

  bool _canLoadMore = false;

  /// 是否可以上拉加载更多
  bool get canLoadMore => _canLoadMore;

  set canLoadMore(bool value) {
    _canLoadMore = value;
  }

  ///是否需要列表cell上报
  bool needReportCell = false;

  // 缓存数据
  Map<String, dynamic>? get cacheMap => null;

  //  测试假数据
  bool? get mapLocalTestList => false;

  /// 是否需要 loading
  bool get needLoading => false;

  bool get needAutoRefresh => true;

  // 列表顶部视图
  Widget? get listHeadWidget => null;
  // 列表底部固定视图
  Widget? get listBottomWidget => null;

  /// 请求时携带的额外请求参数,null代表没有额外参数
  Map<String, dynamic>? get extraParams => null;

  // 空白页面提示图
  String? get imageName => null;
  // 空白页面提示文案
  String? get showEmptyText => null;

  /// 没有内容 或者网络错误,
  Widget get emptyOrErrorWidget {
    return TDEmptyOrNetworkErrorWidget(
      imageName: imageName,
      showEmptyText: showEmptyText,
      isNetWorkError: downRequestFail,
      isDarkPage: isDarkPage,
      retryCallBack: () {
        refreshWithAnimate();
      },
    );
  }

  /// 获取当前的列表数目
  int get itemCount => _listValueNotifier.length;

  /// 最后一个元素的下标
  int get lastIndex => itemCount - 1;

  /// 获取当前的列表是否为空
  bool get isEmpty => _listValueNotifier.isEmpty == true;

  /// 获取当前的列表是否不为空
  bool get isNotEmpty => _listValueNotifier.isNotEmpty == true;

  CancelToken? _cancelToken;

  /// 当前是否加载中
  bool? get isLoading => _cancelToken?.isCancelled == false;

  /// 展示方向
  Axis get scrollDirection => Axis.vertical;

  Color refreshColor = Colors.white;

  int currentPage = 1;
  // 深色页面
  bool isDarkPage = false;

  /// 子类调用,请求父类刷新当前列表
  callRefreshNoAnimate() {
    if (!mounted) return;
    _cancelToken?.cancel();
    requestData(true);
  }

  refreshWithAnimate() {
    _easyRefreshController.callRefresh();
  }

  scrollToTop() {
    // 判断是否可以向上滚动
    bool isScrollableUp = scrollController.hasClients &&
        scrollController.offset >
            (scrollController.position.minScrollExtent ?? 0);
    if (isScrollableUp) {
      scrollController.animateTo(0,
          duration: Duration.zero, curve: Curves.ease);
    }
  }

  /// 遍历当前列表
  forEach(Function(Data data) fun) => _listValueNotifier.forEach(fun);

  /// 移除指定的元素
  remove(Data data) => _listValueNotifier.remove(data);

  /// 移除指定下标的元素
  removeAt(int index) => _listValueNotifier.removeAt(index);

  /// 追加元素
  appendData({int? position, required Data data}) =>
      _listValueNotifier.appendData(data, position);

  /// 追加元素
  appendAllData({int? position, required Iterable<Data> data}) =>
      _listValueNotifier.appendAllData(data, position);

  /// 移除全部的元素
  removeAll() => _listValueNotifier.removeAll();

  /// 获取指定下标的元素
  getDataAt(int index) => _listValueNotifier.getDataAt(index);

  /// 获取全部的元素
  List<Data> getAllData() => _listValueNotifier.getAllData();

  /// 刷新回调
  onRefreshListener() {}

  /// 加载更多回调
  onLoadListener() {}

  /// 检查是否没有更多数据
  checkNoMore(List<dynamic> list, int limit) =>
      list.length < limit || list.isEmpty;

  /// 接收到服务器的数据
  /// request 请求的参数 response 返回的响应
  /// return 解析完毕的数据
  List<Data> receiveData(bool isDownRequest, Map<String, dynamic> response) {
    return parsingData(isDownRequest, response);
  }

  /// 解析数据
  /// return MineTeacherListModel.fromJson(_response);
  List<Data> parsingData(bool isDownRequest, Map<String, dynamic> response);

  /// 对中间的内容布局进行构建,默认为直接一级列出
  /// 返回的元素需要为 [Sliver] 家族成员
  Widget? buildContent(BuildContext context, List<Data> list) {
    if (firstRequest && cacheMap == null) {
      return CustomScrollView(controller: scrollController, slivers: [
        SliverFillViewport(
            delegate: SliverChildListDelegate([
          BlankPage(
            backgroundColor: isDarkPage ? const Color(0xFF1B1528) : null,
          )
        ])),
      ]);
    } else if (!firstRequest && this.isEmpty == true && cacheMap == null) {
      return CustomScrollView(controller: scrollController, slivers: [
        SliverFillViewport(
            delegate: SliverChildListDelegate([emptyOrErrorWidget])),
      ]);
    }

    Widget contents = CustomScrollView(controller: scrollController, slivers: [
      SliverToBoxAdapter(child: listHeadWidget ?? Gap.empty),
      SliverList(
        delegate: SliverChildBuilderDelegate(
          (context, index) => createItemWidget(context, list[index], index),
          childCount: list.length,
        ),
      ),
      SliverToBoxAdapter(
        child: Container(
          height: 80.0, // 设置一个高度为100.0的Container来创建底部空白
        ),
      ),
    ]);
    if (listBottomWidget != null) {
      contents = Column(
        children: <Widget>[
          Expanded(child: contents),
          listBottomWidget!,
        ],
      );
    }
    return contents;
  }

  /// 创建单个条目的布局
  Widget createItemWidget(BuildContext context, Data data, int index);

  final EasyRefreshController _easyRefreshController = EasyRefreshController(
    controlFinishRefresh: true,
    controlFinishLoad: true,
  );
  final ScrollController scrollController = ScrollController();
  //默认分页大小20条
  int get limit => 20;

  @override
  initState() {
    super.initState();

    Future.delayed(Duration.zero, () {
      if (cacheMap != null) {
        List<Data> listModel = [];
        if (cacheMap is Map) {
          listModel = parsingData(false, (cacheMap ?? {}).stringDynamicMap());
        }
        if (listModel.isNotEmpty) {
          this._listValueNotifier.replaceAll(listModel);
        }
      }
    });
    if (needLoading) {
      JDLoadingTool.showLoading();
      requestData(true);
    }
  }

  bool firstRequest = true;
  // 没数据时候 是否显示重试按钮
  bool get showFailEmpty => false;
  JDRefreshHeader header = const JDRefreshHeader();
  JDLoadingFooter footer = const JDLoadingFooter();

  buildEasyRefresh(BuildContext context) {
    return ValueListenableBuilder(
      valueListenable: _listValueNotifier,
      builder: (BuildContext context, List<Data> value, Widget? child) {
        return EasyRefresh(
          controller: _easyRefreshController,
          scrollController: scrollController,
          refreshOnStart: needAutoRefresh,
          header: isDarkPage ? const YouthWhiteRefreshHeader() : header,
          footer: isDarkPage ? const YouthWhiteLoadingFooter() : footer,
          onRefresh: () {
            onRefreshListener();
            requestData(true);
          },
          onLoad: () {
            onLoadListener();
            requestData(false);
          },
          child: needReportCell
              ? ReportListWidget(
                  listValueNotifier: _listValueNotifier,
                  child: buildContent(context, value ?? []),
                )
              : buildContent(context, value ?? []),
        );
      },
    );
  }

  // 下拉请求是否失败
  bool downRequestFail = false;

  requestData(bool isDownRefresh) async {
    if (isDownRefresh) {
      currentPage = 1;
    }
    jdLog('requestData----$currentPage');
    Map<String, dynamic> params = {};
    params['page'] = currentPage;
    if (extraParams != null) {
      params.addAll(extraParams!);
    }
    if (apiUrlRequest.requestParams != null) {
      params.addAll(apiUrlRequest.requestParams!);
    }
    this._cancelToken = CancelToken();
    JDApiRequest moreRequest = apiUrlRequest
      ..params(params)
      ..cancelToken(this._cancelToken);
    Map<String, dynamic> response;
    try {
      response = await moreRequest.request;
    } catch (onError) {
      jdLog('base_list请求出错--> $onError');
      response = {};
    }
    List<Data> modelList = [];
    if (response.responseSucceed() || mapLocalTestList == true) {
      try {
        modelList =
            receiveData(currentPage == 1, Map<String, dynamic>.from(response));
      } catch (onError) {
        jdLog('onError---> ${onError.toString()}');
      }
      final list =
          (currentPage == 1) ? <Data>[] : _listValueNotifier.getAllData();

      this._listValueNotifier.replaceAll([...list, ...modelList]);
      downRequestFail = false;
    } else {
      //本次请求失败
      if (currentPage == 1) {
        downRequestFail = true;
      }
    }
    if (currentPage == 1) {
      finishDownRefresh();
    }
    Map itemMap = response.getMapNotNull(kItems);
    canLoadMore = itemMap.getBoolNotNull('is_next');
    this._easyRefreshController.finishLoad(
        !canLoadMore ? IndicatorResult.noMore : IndicatorResult.success, true);

    if (canLoadMore) {
      this.currentPage = (currentPage + 1);
    }

    if (firstRequest) {
      if (cacheMap == null) {
        Future.delayed(const Duration(milliseconds: 10), () {
          setState(() {
            firstRequest = false;
          });
        });
      } else {
        setState(() {
          firstRequest = false;
        });
      }
    }
    JDLoadingTool.dismissLoading();
  }

  reloadData(List<Data> modelList) {
    this._listValueNotifier.replaceAll(modelList);
  }

  finishDownRefresh() {
    this._easyRefreshController.finishRefresh(IndicatorResult.success, true);
  }

  @override
  dispose() {
    this._cancelToken?.cancel();
    scrollController.dispose();
    _easyRefreshController.dispose();
    super.dispose();
  }
}

// 空白页面 或者网络错误
class TDEmptyOrNetworkErrorWidget extends StatelessWidget {
  final bool isNetWorkError;
  String? imageName;
  final String? showEmptyText;
  final VoidCallback? retryCallBack;
  final Color? backgroundColor;
  final bool isDarkPage;
  TDEmptyOrNetworkErrorWidget(
      {super.key,
      this.isNetWorkError = false,
      this.retryCallBack,
      this.showEmptyText,
      this.isDarkPage = false,
      this.imageName,
      this.backgroundColor});

  @override
  Widget build(BuildContext context) {
    imageName ??= 'empty_default';
    return Container(
      width: JDDevice.width,
      height: JDDevice.height,
      color: backgroundColor ??
          (isDarkPage ? const Color(0xFF1B1528) : Colors.white),
      child: Column(
        children: [
          150.vGap,
          JDAssetImage(
            isNetWorkError
                ? '$fCommonFolder/network_error.png'
                : '$fCommonFolder/$imageName',
            size: const Size(177, 177),
          ),
          12.vGap,
          Text(isNetWorkError ? '当前网络不可用，请检查网络设置' : (showEmptyText ?? '这里空空如也'),
              style: TextStyle(
                  fontSize: 14.0,
                  color: isDarkPage
                      ? const Color(0x99FFFFFF)
                      : const Color(0xFF717880))),
          13.vGap,
          Visibility(
            visible: isNetWorkError,
            child: JDButton(
              backgroundColor:
                  isNetWorkError ? Colors.transparent : Colors.white,
              minWidth: 103,
              minHeight: 33,
              radius: 33.0 / 2.0,
              textStyle: TextStyle(
                  color: isDarkPage
                      ? const Color(0x99FFFFFF)
                      : const Color(0xFF717880),
                  fontSize: 14),
              side: const BorderSide(color: Color(0xFF979797), width: 0.5),
              onPressed: () {
                retryCallBack?.call();
              },
              text: "重新加载",
            ),
          ),
        ],
      ),
    );
  }
}

/// 扩展了[BaseListWidgetMixin]的[State]
abstract class CommonListWidgetState<Data, T extends StatefulWidget>
    extends BaseLifecycleState<T>
    with AutomaticKeepAliveClientMixin, BaseListWidgetMixin<Data, T> {
  @override
  bool get wantKeepAlive => false;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return buildEasyRefresh(context);
  }

  // 显示
  @override
  void onResumed() {
    super.onResumed();
    if (isLeaved) {
      isLeaved = false;
      if (firstRequest || isEmpty) {
        callRefreshNoAnimate();
      }
    }
  }

  bool isLeaved = false;
  @override
  void onPaused() {
    isLeaved = true;
    IndicatorState? headState = _easyRefreshController.headerState;
    if ((headState?.offset ?? -1) > 0) {
      if (scrollController.positions.isNotEmpty) {
        // 页面消失 如果下来刷新控件没完成 取消刷新
        _easyRefreshController.finishRefresh(IndicatorResult.success, true);
        scrollController.jumpTo(0);
      }
    }
    super.onPaused();
  }
}
